package com.gokzzz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gokzzz.dto.SysQuartzJobSaveOrUpdateDTO;
import com.gokzzz.dto.SysQuartzJobSearchQueryDTO;
import com.gokzzz.entity.SysQuartzJob;
import com.gokzzz.exception.RunException;
import com.gokzzz.mapper.SysQuartzJobMapper;
import com.gokzzz.quartz.QuartzManage;
import com.gokzzz.response.PageData;
import com.gokzzz.service.ISysQuartzJobService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * @author ganfujia
 * @date 2022/4/22 15:56
 */
@Service
@RequiredArgsConstructor
public class SysQuartzJobServiceImpl extends ServiceImpl<SysQuartzJobMapper, SysQuartzJob> implements ISysQuartzJobService {
    private final SysQuartzJobMapper sysQuartzJobMapper;

    private final QuartzManage quartzManage;

    @Override
    public PageData<SysQuartzJob> listJobByPage(SysQuartzJobSearchQueryDTO sysQuartzJobSearchQueryDTO, Long page, Long size) {
        LambdaQueryWrapper<SysQuartzJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(CharSequenceUtil.isNotBlank(sysQuartzJobSearchQueryDTO.getJobName()), SysQuartzJob::getJobName, sysQuartzJobSearchQueryDTO.getJobName());
        if (CollUtil.isNotEmpty(sysQuartzJobSearchQueryDTO.getCreateTime()) && ObjectUtil.isNotNull(sysQuartzJobSearchQueryDTO.getCreateTime())) {
            wrapper.between(SysQuartzJob::getCreateTime, sysQuartzJobSearchQueryDTO.getCreateTime().get(0), sysQuartzJobSearchQueryDTO.getCreateTime().get(1));
        }
        Page<SysQuartzJob> sysQuartzJobPage = sysQuartzJobMapper.selectPage(new Page<>(page, size), wrapper);
        return new PageData<>(sysQuartzJobPage.getCurrent(), sysQuartzJobPage.getSize(), sysQuartzJobPage.getTotal(), sysQuartzJobPage.getRecords());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveJob(SysQuartzJobSaveOrUpdateDTO sysQuartzJobSaveOrUpdateDTO) {
        SysQuartzJob sysQuartzJob = toPO(sysQuartzJobSaveOrUpdateDTO);
        // 判断是否存在
        LambdaQueryWrapper<SysQuartzJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysQuartzJob::getJobName, sysQuartzJob.getJobName());
        List<SysQuartzJob> sysQuartzJobs = sysQuartzJobMapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(sysQuartzJobs)) {
            throw new RunException("任务名称已存在");
        }
        sysQuartzJobMapper.insert(sysQuartzJob);
        quartzManage.createScheduler(sysQuartzJob);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateJob(SysQuartzJobSaveOrUpdateDTO sysQuartzJobSaveOrUpdateDTO) {
        SysQuartzJob sysQuartzJob = toPO(sysQuartzJobSaveOrUpdateDTO);
        // 判断是否存在
        LambdaQueryWrapper<SysQuartzJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysQuartzJob::getJobName, sysQuartzJob.getJobName());
        wrapper.ne(SysQuartzJob::getId, sysQuartzJob.getId());
        List<SysQuartzJob> sysQuartzJobs = sysQuartzJobMapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(sysQuartzJobs)) {
            throw new RunException("任务名称已存在");
        }
        sysQuartzJobMapper.updateById(sysQuartzJob);
        quartzManage.updateJobCron(sysQuartzJob);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteJob(Set<Long> ids) {
        List<SysQuartzJob> sysQuartzJobs = sysQuartzJobMapper.selectBatchIds(ids);
        sysQuartzJobMapper.deleteBatchIds(ids);
        sysQuartzJobs.forEach(quartzManage::deleteScheduler);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pauseJob(Long id) {
        SysQuartzJob sysQuartzJob = sysQuartzJobMapper.selectById(id);
        if (ObjectUtil.isNull(sysQuartzJob)) {
            throw new RunException("任务不存在");
        }
        sysQuartzJob.setPause(true);
        sysQuartzJobMapper.updateById(sysQuartzJob);
        quartzManage.pauseScheduler(sysQuartzJob);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resumeJob(Long id) {
        SysQuartzJob sysQuartzJob = sysQuartzJobMapper.selectById(id);
        if (ObjectUtil.isNull(sysQuartzJob)) {
            throw new RunException("任务不存在");
        }
        sysQuartzJob.setPause(false);
        sysQuartzJobMapper.updateById(sysQuartzJob);
        quartzManage.resumeScheduler(sysQuartzJob);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void runJob(Long id) {
        SysQuartzJob sysQuartzJob = sysQuartzJobMapper.selectById(id);
        if (ObjectUtil.isNull(sysQuartzJob)) {
            throw new RunException("任务不存在");
        }
        quartzManage.runScheduler(sysQuartzJob);
    }

    /**
     * 实体转换
     * @param sysQuartzJobSaveOrUpdateDTO DTO
     * @return PO
     */
    private SysQuartzJob toPO(SysQuartzJobSaveOrUpdateDTO sysQuartzJobSaveOrUpdateDTO) {
        SysQuartzJob sysQuartzJob = new SysQuartzJob();
        BeanUtils.copyProperties(sysQuartzJobSaveOrUpdateDTO, sysQuartzJob);
        return sysQuartzJob;
    }
}
